package com.faxsun.admin.controller;

import java.beans.PropertyEditorSupport;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.payment.domain.PaymentTransaction;
import org.broadleafcommerce.openadmin.web.controller.AdminAbstractController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.faxsun.admin.service.RefundService;
import com.faxsun.admin.web.domain.OrderInfoJSON;
import com.faxsun.admin.web.domain.ResponseEntity;
import com.faxsun.admin.web.domain.form.RefundInfoForm;
import com.faxsun.admin.web.domain.util.JSONConventor;
import com.faxsun.core.order.domain.FSOrderImpl;
import com.faxsun.core.order.service.type.FSInternalOrderStatus;

/**
 * 
 * @author zhaoteng.song@faxsun.com
 *
 */
@Controller
@RequestMapping("/" + RefundController.SECTION_KEY)
public class RefundController extends AdminAbstractController {

	protected static final String SECTION_KEY = "refund";

	protected static final String ORDER_NUMBER = "order.orderNumber";
	protected static final String ORDER_ID = "orderId";

	protected static final String JSON_FAIL = "fail";
	protected static final String JSON_SUCC = "success";

	@Resource(name = "refundService")
	protected RefundService refundService;

	/**
	 * 待退款订单列表
	 * 
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/tobelist", method = RequestMethod.GET)
	public String listToBeRefund(HttpServletRequest request,
			HttpServletResponse response, Model model) throws Exception {

		List<Order> orders = refundService.listToBeRefund();
		model.addAttribute("orders", orders);

		model.addAttribute("viewType", "tobelist");
		setModelAttributes(model, SECTION_KEY);
		return "/refundview/default";
	}

	/**
	 * 已退款订单列表
	 * 
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/refundedlist", method = RequestMethod.GET)
	public String listRefunded(HttpServletRequest request,
			HttpServletResponse response, Model model) throws Exception {
		List<Order> orders = refundService.listRefundOrder();
		model.addAttribute("orders", orders);

		model.addAttribute("viewType", "refundedlist");
		setModelAttributes(model, SECTION_KEY);
		return "/refundview/default";
	}

	/**
	 * Ajax 返回Order信息
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/orderinfo", method = RequestMethod.GET, produces = "text/html;charset=UTF-8")
	@ResponseBody
	public String retrieveOrder(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		String orderNumber = request.getParameter(ORDER_NUMBER);
		OrderInfoJSON orderJson = new OrderInfoJSON();

		if (orderNumber == null || orderNumber.isEmpty()) {
			// json error,fail
			orderJson.setRet(JSON_FAIL);
			orderJson.setError("订单号为空");
		} else {
			// order available amount,order total amount, order number, success
			FSOrderImpl order = (FSOrderImpl) this.refundService
					.readOrderByOrderNumber(orderNumber);

			if (order != null && isRefundable(order)) {
				orderJson.setRet(JSON_SUCC);
				orderJson.setOrderNumber(orderNumber);
				orderJson.setOrderAmount(order.getTotal().getAmount());
				BigDecimal availableAmount = this.refundService
						.calulateRemainingRefundAmount(order);
				orderJson.setAvailableAmount(availableAmount);
			} else {
				// json error
				orderJson.setRet(JSON_FAIL);
				orderJson.setError("订单号为不存在或无退货订单");
			}

		}
		return JSONConventor.convertObjectToJSON(orderJson);
	}

	private boolean isRefundable(Order order) {
		FSInternalOrderStatus status = ((FSOrderImpl) order)
				.getInternalStatus();
		if (status == null
				|| (!status.equals(FSInternalOrderStatus.REFUND_REQUEST) && !status
						.equals(FSInternalOrderStatus.REFUND_PROCESSING)))
			return false;
		else
			return true;
	}

	/**
	 * 退款交易记录表
	 * 
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/refunds", method = RequestMethod.GET)
	public String retrievRefunds(HttpServletRequest request,
			HttpServletResponse response, Model model) throws Exception {

		String orderId = request.getParameter(ORDER_ID);

		List<PaymentTransaction> refundlist = new ArrayList<PaymentTransaction>();
		if (orderId == null || orderId.isEmpty()) {

			refundlist = this.refundService.listRefundedTransaction();
		} else {
			refundlist = this.refundService
					.listRefundedTransactionByOrder(orderId);
		}

		model.addAttribute("refunds", refundlist);
		model.addAttribute("viewType", "refundlist");
		setModelAttributes(model, SECTION_KEY);
		return "/refundview/default";
	}

	/**
	 * ajax 退款处理
	 * 
	 * @param request
	 * @param model
	 * @param refundForm
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/refund", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
	@ResponseBody
	public String refund(HttpServletRequest request, Model model,
			@ModelAttribute("refundInfoForm") RefundInfoForm refundForm)
			throws Exception {

		if (refundForm.getAmount().equals(BigDecimal.ZERO)
				|| refundForm.getAmount().compareTo(
						refundForm.getAvaliableAmount()) > 0) {
			return "{\"succ\":false}";
		}

		ResponseEntity retValue = refundService.executeRefund(refundForm);
		setModelAttributes(model, SECTION_KEY);

		return JSONConventor.convertObjectToJSON(retValue);
	}

	@RequestMapping(value = "/refund", method = RequestMethod.GET)
	public String refundGet(HttpServletRequest request, Model model,
			@ModelAttribute("refundInfoForm") RefundInfoForm shippingForm)
			throws Exception {

		String orderNumber = request.getParameter("order.orderNumber");
		if (orderNumber != null && !orderNumber.isEmpty()) {

			FSOrderImpl order = (FSOrderImpl) this.refundService
					.readOrderByOrderNumber(orderNumber);

			if (order != null) {
				shippingForm.setOrder(order);
			}
		}

		model.addAttribute("viewType", "refundform");
		setModelAttributes(model, SECTION_KEY);
		return "/refundview/default";
	}

	@InitBinder
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		binder.registerCustomEditor(Order.class, ORDER_NUMBER,
				new PropertyEditorSupport() {
					@Override
					public void setAsText(String text) {
						if (StringUtils.isNotEmpty(text)) {
							Order order = refundService
									.readOrderByOrderNumber(text);
							setValue(order);
						} else {
							setValue(null);
						}
					}
				});
	}

	@ModelAttribute("refundInfoForm")
	public RefundInfoForm initRefundInfoForm() {
		RefundInfoForm refunInfoForm = new RefundInfoForm();
		refunInfoForm.setOrder(this.refundService.createOrder());
		return refunInfoForm;
	}
}
